//
//  XSDownloadManagerM3u8.m
//  XSDownloadDemo
//
//  Created by 大帅 on 2024/1/4.
//

#import "XSDownloadManagerM3u8.h"

#import "MCSAssetExporterManager.h"

@interface XSDownloadManagerM3u8 () <XSM3u8DownloadDelegate>
{
    XSM3u8Download *downLoad;
}
/* 2秒前的时间 */
@property (nonatomic, strong) NSDate *lastDate;
/* 2秒的数据长度 */
@property (nonatomic, assign) long long dataLength;

@end

@implementation XSDownloadManagerM3u8

static XSDownloadManagerM3u8 *_sharedSingleton = nil;

+ (instancetype)sharedManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 不能再使用 alloc 方法
        // 因为已经重写了 allocWithZone 方法，所以这里要调用父类的分配空间的方法
        _sharedSingleton = [[super allocWithZone:NULL] init];
    });
    return _sharedSingleton;
}

// 防止 [[A alloc] init] 和 new 引起的错误。因为 [[A alloc] init] 和 new 实际是一样的工作原理，都是执行了下面方法
+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    return [XSDownloadManagerM3u8 sharedManager];
}

// NSCopying 防止 copy 引起的错误。当你的单例类不遵循 NSCopying 协议，外部调用本身就会出错.
- (id)copyWithZone:(nullable NSZone *)zone {
    return [XSDownloadManagerM3u8 sharedManager];
}

// 防止 mutableCopy 引起的错误，当你的单例类不遵循 NSMutableCopying 协议，外部调用本身就会出错.
- (id)mutableCopyWithZone:(nullable NSZone *)zone {
    return [XSDownloadManagerM3u8 sharedManager];
}

-(instancetype)init {
    if (self = [super init]) {
        SJMediaCacheServer.shared.enabledConsoleLog = NO;
        SJMediaCacheServer.shared.logOptions = MCSLogOptionDefault;
        SJMediaCacheServer.shared.cacheCountLimit = 1;
        SJMediaCacheServer.shared.maxDiskAgeForCache = 10;
        SJMediaCacheServer.shared.maxDiskSizeForCache = 10;
        // 单位是字节, 这里设置为保留剩余空间 1G
        SJMediaCacheServer.shared.reservedFreeDiskSpace = 1 * 1024 * 1024 * 1024;
    }
    return self;
}

// 是否存在正在下载的任务
-(BOOL)downLoading {
    NSArray <id<MCSAssetExporter>> *exportIngArr = [MCSAssetExporterManager.shared exportsForMask:MCSAssetExportStatusQueryMaskExporting];
    return exportIngArr.count > 0 ? YES : NO;
}

/// 加入下载任务开始下载
- (void)addDownloadingTask:(XSTestModel *)model {    
    
    if (![self netWorkAllowDownloadTask]) {
        [[XSToastView shareManager] showMessage:@"当前无网络"];
        return;
    }
    
    // 检查数据库中是否存在，不存在则加入
    XSTestModel *downloadModel = [[XSDataSaveManager sharedManager] lookDownloadSingleData:model];
    // 数据库中不存在就则加入数据库中
    if (!downloadModel) {
        downloadModel = model;
        downloadModel.state = XSDownloadStatusWaiting;
        [[XSDataSaveManager sharedManager] addDownloadSingleData:downloadModel];
    } else {
        if (downloadModel.state != XSDownloadStatusFinish && downloadModel.state != XSDownloadStatusWaiting) {
            downloadModel.state = XSDownloadStatusWaiting;
            [[XSDataSaveManager sharedManager] updateDownloadSingleData:downloadModel];
        }
    }
    
    // 创建下载对象
    if (!downLoad) {
        downLoad = [[XSM3u8Download alloc] initWithMedia:downloadModel];
        downLoad.delegate = self;
        dispatch_async(dispatch_get_global_queue(0, 0), ^{
            if (self->downLoad.exporter) {
                if ([self netWorkAllowDownloadTask]) {
                    [self->downLoad.exporter resume];
                }
            }
        });
    }
}

/// 开始等待下载的任务（只开始等待中的任务）
- (void)startAllWaitDataDownloadTask {
    // 检查数据库中是否存在，不存在则加入
    NSArray *allList = [[XSDataSaveManager sharedManager] lookDownloadAllData];
    if (allList.count <= 0) return;
    // 按顺序查找第一条需要下载的任务
    __block XSTestModel *downloadModel;
    [allList enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        XSTestModel *model = (XSTestModel *)obj;
        if (model.state != XSDownloadStatusFinish && model.state != XSDownloadStatusPause) {
            downloadModel = model;
            *stop = YES;
        }
    }];
    if (!downloadModel) return;
    [self addDownloadingTask:downloadModel];
}

/// 开始全部下载任务（除未下载完成以外所有任务）
- (void)startAllDataDownloadTask:(NSArray *)list {
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    [list enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        XSTestModel *model = (XSTestModel *)obj;
        if (![[XSDataSaveManager sharedManager] lookDownloadSingleData:model]) {
            model.state = XSDownloadStatusWaiting;
            [arr addObject:model];
        } else {
            if (model.state != XSDownloadStatusFinish) {
                model.state = XSDownloadStatusWaiting;
                // 更新数据库
                [[XSDataSaveManager sharedManager] updateDownloadSingleData:model];
            }
        }
    }];
    if (arr.count > 0) {
        // 加入数据库下载队列
        [[XSDataSaveManager sharedManager] addDownloadMoreData:arr];
    }
    // 开始下载
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self startAllWaitDataDownloadTask];
    });
}

#pragma mark ——— 查询本地的下载视频监听对象
- (XSM3u8Download *)checkExporterWithMediaModel:(XSTestModel *)model{
    XSM3u8Download *download;
    // 查询本地的下载视频对象
    XSTestModel *localMedia = [[XSDataSaveManager sharedManager] lookDownloadSingleData:model];;
    if (localMedia) {
        download = [[XSM3u8Download alloc] initWithMedia:localMedia];
        download.delegate = self;
    }
    return download;
}

/// 暂停指定下载任务
- (void)pauseDownloadingTask:(XSTestModel *)model {
    if (model.state == XSDownloadStatusDownloading) {
        if (self->downLoad.exporter) {
            [self->downLoad.exporter suspend];
        } else {
            model.state = XSDownloadStatusPause;
            // 更新数据库
            [[XSDataSaveManager sharedManager] updateDownloadSingleData:model];
        }
    } else {
        model.state = XSDownloadStatusPause;
        // 更新数据库
        [[XSDataSaveManager sharedManager] updateDownloadSingleData:model];
    }
}

/// 暂停全部下载任务
- (void)pauseAllDataDownloadingTask {
    if (self->downLoad.exporter) {
        [self->downLoad.exporter suspend];
    }
    // 检查数据库中是否存在，不存在则加入
    NSArray *allList = [[XSDataSaveManager sharedManager] lookDownloadAllData];
    if (allList.count <= 0) return;
    [allList enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        XSTestModel *model = (XSTestModel *)obj;
        if (model.state != XSDownloadStatusFinish) {
            model.state = XSDownloadStatusPause;
            // 更新数据库
            [[XSDataSaveManager sharedManager] updateDownloadSingleData:model];
        }
    }];
}

/// 删除下载任务及本地缓存
- (BOOL)deleteDownloadingTask:(XSTestModel *)model {
    // 获取数据库数据
    __block BOOL isDown = NO;
    XSTestModel *downloadModel = [[XSDataSaveManager sharedManager] lookDownloadSingleData:model];
    if (downloadModel) {
        // 检查要删除的是否正在下载中的（是则取消下载）
        if (downloadModel.state == XSDownloadStatusDownloading) {
            if (self->downLoad.exporter) {
                [self->downLoad.exporter cancel];
            } else {
                self->downLoad = [self checkExporterWithMediaModel:model];
                [self->downLoad.exporter cancel];
            }
            isDown = YES;
        }
    }
    // 删除数据库对应下载数据
    BOOL isFin = [[XSDataSaveManager sharedManager] deleteM3u8DownloadSingleData:model];
    if (isDown) {
        // 删除正在下载的开启下一个
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            self->downLoad = nil;
            [self startAllWaitDataDownloadTask];
        });
    }
    return isFin;
}

/// 批量删除
- (BOOL)deleteMoreListTask:(NSArray *)delList {
    [delList enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        XSTestModel *model = (XSTestModel *)obj;
        if (model.state == XSDownloadStatusDownloading) {
            if (self->downLoad.exporter) {
                [self->downLoad.exporter cancel];
            } else {
                self->downLoad = [self checkExporterWithMediaModel:model];
                [self->downLoad.exporter cancel];
            }
        }
        // 删除数据库对应下载数据
        [[XSDataSaveManager sharedManager] deleteM3u8DownloadSingleData:model];
    }];
    return YES;
}

#pragma mark --- XSM3u8DownloadDelegate
// 下载状态改变
- (void)exporter:(id<MCSAssetExporter>)exporter statusDidChange:(MCSAssetExportStatus)status mediaModel:(XSTestModel *)mediaModel {
    XSTestModel *downloadModel = [[XSDataSaveManager sharedManager] lookDownloadSingleData:mediaModel];
    if (downloadModel) {
        downloadModel.speed = 0;
        switch (status) {
            case MCSAssetExportStatusUnknown:
                downloadModel.state = XSDownloadStatusError;
                self->downLoad = nil;
                break;
                
            case MCSAssetExportStatusWaiting:
                downloadModel.state = XSDownloadStatusWaiting;
                break;
                
            case MCSAssetExportStatusExporting:
                downloadModel.state = XSDownloadStatusDownloading;
                break;
                
            case MCSAssetExportStatusFinished:
                downloadModel.state = XSDownloadStatusFinish;
                downloadModel.locaM3u8lUrl = [[SJMediaCacheServer shared] playbackURLWithURL:[NSURL URLWithString:downloadModel.url]].absoluteString;
                self->downLoad = nil;
                break;
                
            case MCSAssetExportStatusFailed:
                downloadModel.state = XSDownloadStatusError;
                self->downLoad = nil;
                break;
                
            case MCSAssetExportStatusSuspended:
                downloadModel.state = XSDownloadStatusPause;
                self->downLoad = nil;
                break;
                
            case MCSAssetExportStatusCancelled:
                downloadModel.state = XSDownloadStatusError;
                self->downLoad = nil;
                break;
                
            default:
                break;
        }
        // 更新数据库
        [[XSDataSaveManager sharedManager] updateDownloadSingleData:downloadModel];
        if (self->downLoad == nil) {
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [self startAllWaitDataDownloadTask];
            });
        }
    }
}

// 下载进度改变
- (void)exporter:(id<MCSAssetExporter>)exporter progressDidChange:(float)progress mediaModel:(XSTestModel *)mediaModel {
    XSTestModel *downloadModel = [[XSDataSaveManager sharedManager] lookDownloadSingleData:mediaModel];
    if (downloadModel) {
        downloadModel.progress = progress;
        //downloadModel.downloadSizeM3u8 = exporter.downSize;
        downloadModel.totalSizeM3u8 = downloadModel.totalSizeM3u8 <= 0 ? exporter.totalSize : downloadModel.totalSizeM3u8;
        downloadModel.downloadSizeM3u8 = downloadModel.totalSizeM3u8 * progress;
        // 每秒下载速度计算
        NSDate *currentDate = [NSDate date];
        if (_dataLength > 0) {
            NSTimeInterval interval = [currentDate timeIntervalSinceDate:_lastDate];
            if (interval >= 1) {
                downloadModel.speed = (downloadModel.downloadSizeM3u8 - _dataLength) / interval;
                _lastDate = currentDate;
                _dataLength = 0;
            }
        } else {
            _lastDate = currentDate;
            _dataLength = downloadModel.downloadSizeM3u8;
        }
        [[XSDataSaveManager sharedManager] updateDownloadSingleData:downloadModel];
        
        NSLog(@"当前下载：%@ -> 下载进度：%.02f, %ld, %ld", downloadModel.videoName, progress, downloadModel.downloadSizeM3u8, downloadModel.downloadSizeM3u8);
        
        // 发送下载信息，改变UI
        [[NSNotificationCenter defaultCenter] postNotificationName:XSDownloadM3u8ProgressNotification object:downloadModel];
    }
}

/// 网络检查是否可以下载
- (BOOL)netWorkAllowDownloadTask {
    // 获取网络状态
    AFNetworkReachabilityStatus netState = [[XSNetworkReachabilityManager shareManager] networkReachabilityStatus];
    if (netState != AFNetworkReachabilityStatusReachableViaWiFi) {
        return NO;
    }
    return YES;
}


@end
